home *** CD-ROM | disk | FTP | other *** search
Text File | 2009-10-01 | 45.3 KB | 1,333 lines |
-
- /* Copyright (C) 2009 Norman Solomon
- * e-mail: historytree.addon@yahoo.com
- *
- * The contents of this file are subject to the Mozilla Public License Version
- * 1.1 (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at http://www.mozilla.org/MPL/
- *
- * Software distributed under the License is distributed on an "AS IS" basis,
- * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
- * for the specific language governing rights and limitations under the License.
- */
-
- // ***********************************************************************************
- // ***** *****
- // ***** HISTORY TREE WINDOW TOP-LEVEL JAVASCRIPT FOR "historyViewer.xul" *****
- // ***** ------------------------------------------------------------------- *****
- // ***** 1) Initializes all constants and globals used by all <script> files *****
- // ***** 2) Handles onLoad() and onFocus() which refreshes key arrays etc. *****
- // ***** 3) Handles GUI events for all <..> objects in "historyViewer.xul" *****
- // ***** 4) Contains shared JS functions used by other <script> JS files *****
- // ***** *****
- // ***********************************************************************************
-
- // All globals used by "historyViewer.xul" <script...>'s are declared below.
- // One global and its associated class are declared in "firefoxOverlay.js"
- // No other globals are declared anywhere else in the HistoryTree extension
-
- const CANVAS_MIN_WID = screen.availWidth - 26; // - 26 to enforce vert scrollbar
- const CANVAS_MIN_HGT = screen.availHeight - 80; // Allows for top panel height
- const CANVAS_BAK_COL = "rgb(38,38,38)"; // Dark grey gCanvas backcolor
- const CURR_TAB_COL = "rgb(255,204,170)"; // Orange - Current Tab
- const OPEN_TAB_COL = "rgb(255,255,180)"; // Yellow - Open Tab
- const CLOSED_TAB_COL = "rgb(180,190,220)"; // Blue - Closed Tab
-
- const WH_RATIO = 0.65; // w/h ratio for all drawm ".jpeg" images
- const GRID_VIEW = 1; // Set after <image...> click that shows GridView
- const TREE_VIEW = 2; // Set after <image...> click that shows TreeView
- const GV_HGAP = 23; // Horizontal gap between drawn GridView images
- const GV_VGAP = 52; // Vertical gap between drawn GridView images
-
- // ------------------------------------------------------------------------------
- // TreeView constants
- const BOX_WIDTH = 142; // Width of TreeView drawn boxes
- const BOX_HEIGHT = 65; // Height of TreeView drawn boxes
- const BOX_BTN_WID = 21; // Width of buttons below drawn boxes
- const BOX_BTN_HGT = 16; // Height of buttons below drawn boxes
- const LEVEL_SPACE = (BOX_WIDTH * 0.63) * (-1); // Used in attachParent()
- const NODE_BORDER = 41; // *** CRITICAL VALUE - Determines overall tree-size
- const BORDER_STEP = 3; // <scale...> change multiplier (changes tree-size)
- const MAX_IMG_WID = 750; // Maximum size of expanded TV node image
-
- // TreeView mouse event button click constants
- const BTN_NONE = 0; // User clicked on empty TreeView gCanvas area
- const BTN_CHANGE_TREE = 1; // User clicked on expand/shrink sub-tree button
- const BTN_SHOW_IMAGE = 2; // User clicked on "?" show expanded image button
- const BTN_OPEN_PAGE = 3; // User clicked on node to open history page in FF
-
- // --------------------------------------------------------------------------
- // Globals passed from "firefoxOverlay.js" via Application storage
- var gNodeList; // HistoryNode array in "firefoxOverlay.js"
- var gOpenTabIDs; // Array of TabID's that are currently open in FF
- var gParamArray; // Various parameters in a App storage array
- var gCurrentTabID; // TabID of currently open Tab in FF
- var gNodeListLoadLen; // Used in onFocus() to check for FF history changes
-
- // --------------------------------------------------------------------------
- // Globals used by both TreeView and GridView
- var gParentFFWin; // FF window for which history is shown
- var gCanvas; // SVG style Canvas which covers 90% of the window
- var gCtx; // gCanvas '2d' context for all drawing
- var gCanvasScroller; // gCanvas scroller and mouse-click detect object
- var gCurrentView; // Set = TREE_VIEW or GRID_VIEW (see constants above)
- var gSearchIndexes; // Array to enable consistant Find Next/Prev search
- var gSearchNdx; // Current gSearchIndexes[ndx] for Find Next/Prev
- var gGVdispArray; // Array holding images drawn via gGVdispInterval
-
- // Interval timing and function exit flags
- var gTabLoadInterval; // Used to clear setInterval()'s and exit GUI functions
- var gGVdispInterval; // Used to clear GV setInterval() and exit GUI functions
- var gImgExpandInterval; // Used to clear setInterval()'s and exit GUI functions
- var gTimeoutInterval; // Used to clear setTimeout()'s and exit GUI functions
- var gExitWinFocusEvent; // Exits from unwanted firing of window onFocus() event
-
- // --------------------------------------------------------------------------
- // TreeView globals
- var gTabRoots; // Array that stores Tab sub-tree Root TreeNode's
- var gTreeNodes; // Array that stores ALL TreeNode objects (main array)
- var gTreeMinY; // Only used by "treeArranger.js" plantTree()
- var gSubTreeSize; // Only used by "treeArranger.js" walkSubTree()
-
- // TreeView image expansion globals
- var gExpandedNode; // TreeNode that has an expanded image/info box
- var gImgXY; // Expanded image/info box top-left (x,y) on gCanvas
- var gInfoBoxWH; // Expanded image/info box (w,h) on gCanvas
- var gNodeImageWid; // Used to expand and then clear expanded image
-
-
- // ***********************************************************
- // ***** *****
- // ***** WINDOW onLoad() AND onFocus() FUNCTIONALITY *****
- // ***** *****
- // ***********************************************************
-
- // ========================================================
- // Window onLoad event listener, and associated function
- // ========================================================
- window.addEventListener("load", onLoad, false);
- function onLoad()
- {
- try
- {
- // Maximise this window, but leave room for user to resize it
- // (takes account of current screen resolution)
- this.resizeTo(screen.availWidth, screen.availHeight);
- gExitWinFocusEvent = true; // Used in onFocus() event
-
- // Set global FF parent window
- gParentFFWin = window.opener;
-
- // Initialize gCanvas, making sure it fills the window
- gCanvas = document.getElementById('myCanvas');
- gCanvas.width = CANVAS_MIN_WID;
- gCanvas.height = CANVAS_MIN_HGT;
-
- // Fill gCanvas with dark grey blank rectangle
- gCtx = gCanvas.getContext('2d');
- gCtx.fillStyle = CANVAS_BAK_COL; // Dark grey
- gCtx.fillRect(0, 0, gCanvas.width, gCanvas.height);
-
- // Initialize canvas scroller
- var canvasBox = document.getElementById('canvasBox');
- gCanvasScroller = canvasBox.boxObject.QueryInterface
- (Components.interfaces.nsIScrollBoxObject);
-
- // Init key global vars and display history GV or TV
- updateHistoryWhenAllTabsLoaded();
- gExitWinFocusEvent = true;
- this.focus();
- }
- catch (e)
- {
- alert("History Tree Extension - Main Window onLoad() Error");
- }
- }
-
- // ============================================================
- // Extension window onFocus listener and associated function
- // ============================================================
- window.addEventListener("focus", onFocus, false);
- function onFocus()
- {
- // Update history if global exit flag not set
- if (gExitWinFocusEvent)
- {
- gExitWinFocusEvent = false;
- }
- else if (gTabLoadInterval === null)
- {
- // Data update setInterval() is NOT running
- if (firefoxHistoryChanged())
- {
- // FF history has changed so update gTreeNodes[] etc
- updateHistoryWhenAllTabsLoaded();
- }
- else
- {
- // No additions or deletions to FF history were made, but
- // user may have navigated to, or re-loaded, some pages
- gParentFFWin.historyTree.putWinParamsArrayInAppStorage();
- gParamArray = Application.storage.get("paramArray", null);
- gCurrentTabID = gParamArray[0]; // tabID of FF visible Tab
-
- // Set "Window x of y" label
- setLabelText_WindowXofY();
-
- // Reset search <textbox...> backgroundColor
- var chkSearchURL = document.getElementById("chkSearchURL");
- setSearchTextBoxColor(chkSearchURL.checked);
-
- // Update <listbox...> descriptions and text colors
- updateListboxTabRootDescriptions();
-
- // Redraw view, so that changed gNodeList[] data appears
- if (gCurrentView === TREE_VIEW)
- {
- drawTree(false, null, null);
- }
- else
- {
- var sldDraw = document.getElementById("sldDraw");
- var numAcross = (sldDraw.max - sldDraw.value) + 3;
- drawAllImagesOnCanvas(numAcross, false);
- }
- }
- }
- }
-
- // ====================================================================
- // Returns true if FF history has changed since this window lost focus
- // ====================================================================
- function firefoxHistoryChanged()
- {
- if (gNodeListLoadLen === null
- || gNodeListLoadLen !== gParentFFWin.historyTree.cNodeList.length
- || !gParentFFWin.historyTree.allTabsLoaded())
- {
- // Pages were added, or are being added, to FF history
- return true;
- }
- else if (gParentFFWin.historyTree.recentFFhistoryCleared())
- {
- // "Tools > Clear Recent History" or similar occured
- return true;
- }
- else
- {
- // Check if FF has same number of Tabs as when window lost focus
- var openTabIDs = gParentFFWin.historyTree.openTabIDsList();
- if (openTabIDs.length !== gOpenTabIDs.length)
- {
- // Tabs were opened or closed in FF
- return true;
- }
- else
- {
- // Check if FF TabID list has changed
- for (i = 0; i < openTabIDs.length; i++)
- {
- if (openTabIDs[i] !== gOpenTabIDs[i])
- {
- // Tab list or Tab order has changed in FF
- return true;
- }
- }
- }
- }
-
- // No pages were added to, or removed from, FF history
- return false;
- }
-
- // ====================================================================
- // Updates and shows history when all FF window/page data has loaded
- // Called from onLoad(), onFocus() and Next/Prev window button clicks
- // ====================================================================
- function updateHistoryWhenAllTabsLoaded()
- {
- // Show "Loading..." message while FF loads window/pages
- var loadMsg = "";
- if (gParentFFWin.historyTree.cExtLoadProcess)
- loadMsg = "Loading Firefox window history...";
- else if (!gParentFFWin.historyTree.allTabsLoaded())
- loadMsg = "Loading Firefox page data...";
- else
- loadMsg = "Updating history tree...";
-
- // Show "Loading..." message at top-centre of gCanvas
- showBigMessageOnEmptyCanvas(loadMsg, "bold 14pt verdana");
-
- // Disable "historyViewer.xul" top-panel GUI controls
- disableOrEnableGUIcontrols(true);
-
- // Start setInterval() that loads and shows history
- // (delay is ALWAYS needed to stop slow, "jerky", load)
- gTabLoadInterval = setInterval(loadAndShowHistory, 100);
- }
-
- // ===========================================================
- // Loads App Storage data for FF parent window gParentFFWin,
- // then uses this to init key global vars and show history
- // ===========================================================
- function loadAndShowHistory()
- {
- // Check if all FF parent window Tabs have fully loaded
- if (!gParentFFWin.historyTree.allTabsLoaded()
- || gParentFFWin.historyTree.cExtLoadProcess)
- {
- // Some FF parent window Tab content is still loading
- return;
- }
- else
- {
- // All Tabs loaded, so stop setInterval() (flag reset below)
- clearInterval(gTabLoadInterval);
- }
-
- // ------------------------------------------------
- // Clear any running timeouts/intervals
- clearInterval(gGVdispInterval);
- gGVdispInterval = null;
- clearInterval(gImgExpandInterval);
- gImgExpandInterval = null;
- clearTimeout(gTimeoutInterval);
- gTimeoutInterval = null;
-
- // Set "Window x of y" label
- setLabelText_WindowXofY();
-
- // ------------------------------------------------
- // Call "firefoxOverlay.js" method that puts data in App storage
- gParentFFWin.historyTree.putHistoryDataInAppStorage();
-
- // Set globals using retrieved App storage data
- gNodeList = Application.storage.get("nodeArray", null);
- gOpenTabIDs = Application.storage.get("tabIDarray", null);
- gParamArray = Application.storage.get("paramArray", null);
- gCurrentTabID = gParamArray[0]; // tabID of FF visible Tab
- gNodeListLoadLen = gNodeList.length; // Used in onFocus()
-
- // Initialize other key globals
- gTabRoots = new Array();
- gTreeNodes = new Array();
- gSearchIndexes = new Array();
- gSearchNdx = -1;
- gTreeMinY = 0;
- gSubTreeSize = 0;
- gCurrentView = TREE_VIEW;
- gExpandedNode = null;
- gImgXY = new Point(0, 0);
- gInfoBoxWH = new Point(0, 0);
- gNodeImageWid = 0;
-
- // ---------------------------------------------------
- // Show history view or a "No history" info message
- if (gNodeList.length > 0)
- {
- // Show history view using GUI options saved in App storage
- showLoadedHistoryView();
- }
- else
- {
- // Show a message if no pages in window history *** BUT NOTE
- // gTreeNodes[] and other key globals are NOT set in this case
- showBigMessageOnEmptyCanvas
- ("No pages in window history", "bold 14pt verdana");
- }
-
- // Set reload completion global flag (** DO NOT do this earlier)
- gTabLoadInterval = null;
- }
-
- // ==================================================================
- // Shows FF window history using user's GUI options from App Storage
- // ==================================================================
- function showLoadedHistoryView()
- {
- // Init all vars
- var btnTreeView = document.getElementById("btnTreeView");
- var btnGridView = document.getElementById("btnGridView");
- var lblSliderHdr = document.getElementById("lblSliderHdr");
- var sldDraw = document.getElementById("sldDraw");
- var optGrpView = document.getElementById("optGrpView");
- var chkSearchURL = document.getElementById("chkSearchURL");
- var listSelTab = document.getElementById("listSelTab");
- var viewNum;
- var radioOpt;
- var borderSize;
-
- // ------------------------------------------------------------------
- // Create gTreeNodes[] & gTabRoots[] using retrieved App storage data
- buildFullHistoryTree();
-
- // Create gSearchIndexes[] - Enabling consistant search order
- createGlobalSearchIndexesArray();
-
- // Fill "historyViewer.xul" <listbox...> with Tab root page descs
- // This also sets <listbox...> selected item = gCurrentTabID FF Tab
- fillListboxWithTabRootDescriptions();
-
- // Re-enable "historyViewer.xul" top-panel GUI controls
- disableOrEnableGUIcontrols(false);
- listSelTab.focus(); // <listbox...>
-
- // -----------------------------------------------------------
- // Setup "historyViewer.xul" GUI for GV or TV (default is TV)
- gCurrentView = Application.storage.get("GVorTVbuttonVal", TREE_VIEW);
- if (gCurrentView === GRID_VIEW)
- {
- // Set GUI controls for GridView
- btnGridView.src = "images/btnGVin.gif";
- btnTreeView.src = "images/btnTVout.gif";
- sldDraw.value = Application.storage.get("gridViewSliderVal", 4);
- lblSliderHdr.value = "Image Size";
- }
- else
- {
- // Set GUI controls for TreeView
- btnTreeView.src = "images/btnTVin.gif";
- btnGridView.src = "images/btnGVout.gif";
- sldDraw.value = Application.storage.get("treeViewSliderVal", 1);
- lblSliderHdr.value = "Tree Spacing";
-
- // Reset tree-spacing using slider value
- borderSize = (sldDraw.value * BORDER_STEP) + NODE_BORDER;
- setBorderForAllNodes(borderSize);
- }
-
- // -----------------------------------------------------------
- // Show user's chosen quick-view (default is "Show open tabs")
- if (numExtWinOpenTabs() > 0)
- {
- // Get user's quick-view choice from App Storage
- viewNum = Application.storage.get("quickViewOptGrpVal", 0);
- }
- else
- {
- // No open Tabs - So disable open Tabs quick-view options
- radioOpt = document.getElementById("optOpenTabs");
- radioOpt.disabled = true;
- radioOpt = document.getElementById("optOpenPages");
- radioOpt.disabled = true;
- viewNum = 3; // "Show closed tabs"
- }
-
- // Set <radiogroup...> option for quick-view, then show that quick-view
- optGrpView.selectedIndex = viewNum;
- showQuickView(viewNum);
-
- // Set search <textbox...> backColor - Found = "white", Not found = "red"
- chkSearchURL.checked = Application.storage.get("searchCheckboxVal", true);
- setSearchTextBoxColor(chkSearchURL.checked);
- }
-
- // ==================================================================
- // Fills "historyViewer.xul" <listbox...> with Tab root page descs
- // ==================================================================
- function fillListboxWithTabRootDescriptions()
- {
- // Init vars
- var listSelTab = document.getElementById("listSelTab");
- var listItemTxt;
- var tabRoot;
- var startNdx = 0;
- var listItem;
- var itemTxtCol;
-
- // -------------------------------------------
- // Remove all items from the <listbox...>
- while (listSelTab.itemCount > 0)
- listSelTab.removeItemAt(0);
-
- // Fill the <listbox...> with Tab root descriptions
- for (var i = 0; i < gTabRoots.length; i++)
- {
- // Get Tab root TreeNode object
- tabRoot = gTabRoots[i];
-
- // Set <listbox...> item number prefix
- listItemTxt = (i + 1).toString() + " - ";
-
- // Add web-page description from Tab root HistoryNode
- listItemTxt += tabRoot.histNode.desc;
-
- // Add item to <listbox...> including tabID as item.value
- listSelTab.appendItem(listItemTxt, tabRoot.histNode.tab);
-
- // Set listitem font color
- if (tabRoot.histNode.tab === gCurrentTabID)
- itemTxtCol = "rgb(255,80,0)"; // Orange
- else if (!tabRoot.inOpenTab)
- itemTxtCol = "rgb(61,110,255)"; // Blue
- else
- itemTxtCol = "black";
-
- listItem = listSelTab.getItemAtIndex(i);
- listItem.style.color = itemTxtCol;
-
- // Set <listbox...>.selectedIndex (see *** NOTE below)
- if (tabRoot.histNode.tab === gCurrentTabID)
- startNdx = i;
- }
-
- // ---------------------------------------------------------------
- // Show selected <listbox...> item. This seems like a kludge, but
- // <listbox...> needs time to populate before item can be selected
- listSelTab.ensureIndexIsVisible(startNdx);
- listSelTab.selectedIndex = startNdx;
- gTimeoutInterval = setTimeout
- (setListboxSelectedItem, listSelTab.itemCount * 15, startNdx);
- }
-
- // ============================================================
- // Sets <listbox...> selected item after calculated time delay
- // ============================================================
- function setListboxSelectedItem(startNdx)
- {
- // Stop setTimeout() and set global flag
- clearTimeout(gTimeoutInterval);
- gTimeoutInterval = null;
-
- // Highlight selected <listbox...> item
- var listSelTab = document.getElementById("listSelTab");
- listSelTab.ensureIndexIsVisible(startNdx);
- listSelTab.selectedIndex = startNdx;
- }
-
- // ==========================================================
- // Updates "historyViewer.xul" <listbox...> listItem labels
- // ==========================================================
- function updateListboxTabRootDescriptions()
- {
- // Init vars
- var listSelTab = document.getElementById("listSelTab");
- var tabRoot;
- var listItem;
- var listItemTxt;
- var itemTxtCol;
-
- // --------------------------------------------------
- // Update <listbox...> Tab root descriptions
- for (var i = 0; i < gTabRoots.length; i++)
- {
- // Make sure <listbox...> item exists
- if (listSelTab.itemCount > i)
- {
- // Set listItem label prefix
- tabRoot = gTabRoots[i];
- listItemTxt = (i + 1).toString() + " - ";
-
- // Update listItem.label
- listItem = listSelTab.getItemAtIndex(i);
- listItem.label = listItemTxt + tabRoot.histNode.desc;
-
- // Update listitem font color
- if (tabRoot.histNode.tab === gCurrentTabID)
- itemTxtCol = "rgb(255,80,0)"; // Orange
- else if (!tabRoot.inOpenTab)
- itemTxtCol = "rgb(61,110,255)"; // Blue
- else
- itemTxtCol = "black";
-
- // Set listitem font color
- listItem.style.color = itemTxtCol;
- }
- }
- }
-
- // ****************************************************************
- // ***** *****
- // ***** EVENT HANDLING PROCEDURES *****
- // ***** USED BY BOTH TREE-VIEW AND GRID-VIEW *****
- // ***** *****
- // ****************************************************************
-
- // =================================================================
- // Returns true if invalid setInterval() or setTimeout() is running
- // Prevents use of this window's GUI controls during timed proceses
- // =================================================================
- function setIntervalOrTimeoutRunning()
- {
- if (gTabLoadInterval !== null || gImgExpandInterval !== null
- || gTimeoutInterval !== null)
- {
- // This window's setInterval() or setTimeout() is running
- return true;
- }
- else
- {
- // No window timed events are occuring
- return false;
- }
- }
-
- // ================================================================
- // Called from TWO "historyViewer.xul" <image...> onclick() events
- // ================================================================
- function reloadButtonEventHandler(event)
- {
- // Exit if a setInterval() or setTimeout() is running
- if (setIntervalOrTimeoutRunning() || gGVdispInterval !== null)
- return;
-
- // Init vars
- var btnNextWin, btnPrevWin;
-
- if (event.target.id == "btnNextWin")
- {
- // Show Next FF win button briefly pushed in
- btnNextWin = document.getElementById("btnNextWin");
- btnNextWin.src = "images/btnNextWinIn.gif";
-
- // Load history for Next FF window
- gTimeoutInterval = setTimeout
- (loadHistoryForNextOrPrevFFwindow, 100, true);
- }
- else
- {
- // Show Previous FF win button briefly pushed in
- btnPrevWin = document.getElementById("btnPrevWin");
- btnPrevWin.src = "images/btnPrevWinIn.gif";
-
- // Load history for Previous FF window
- gTimeoutInterval = setTimeout
- (loadHistoryForNextOrPrevFFwindow, 100, false);
- }
- }
-
- // ========================================================
- // Called via setTimeout() from reloadButtonEventHandler()
- // ========================================================
- function loadHistoryForNextOrPrevFFwindow(nextWin)
- {
- // Init vars
- var btnNextWin, btnPrevWin;
-
- // Stop setTimeout() and set global flag
- clearTimeout(gTimeoutInterval);
- gTimeoutInterval = null;
-
- // Show Next/Previous FF win button pushed out
- if (nextWin)
- {
- btnNextWin = document.getElementById("btnNextWin");
- btnNextWin.src = "images/btnNextWinOut.gif";
- }
- else
- {
- btnPrevWin = document.getElementById("btnPrevWin");
- btnPrevWin.src = "images/btnPrevWinOut.gif";
- }
-
- // Set this windows opener as Next/Prev open FF window
- gParentFFWin = nextOrPrevFFwindow(nextWin);
- gParentFFWin.historyTree.cExtHistTreeWin = this;
-
- // Rebuild key global vars and re-display GV or TV
- updateHistoryWhenAllTabsLoaded();
- }
-
- // ===============================================================
- // Called from TWO "historyViewer.xul <image...> onclick() events
- // ===============================================================
- function searchButtonEventHandler(event)
- {
- // Exit if a setInterval() or setTimeout() is running
- if (setIntervalOrTimeoutRunning() || gGVdispInterval !== null
- || gNodeList.length === 0)
- return;
-
- // ------------------------------------------------------
- // Init vars
- var txtFind, chkSearchURL;
- var btnFindNext, btnFindPrev;
- var txtToFind;
- var searchURL;
-
- txtFind = document.getElementById("txtFind");
- txtToFind = (txtFind.value).toUpperCase();
- chkSearchURL = document.getElementById("chkSearchURL");
- searchURL = chkSearchURL.checked;
-
- // Perform search if <textbox...> text is found
- if (txtToFind !== "" && searchTextFound(txtToFind, searchURL))
- {
- if (event.target.id === "btnFindNext")
- {
- // Find Next page with matching <textbox...> text
- btnFindNext = document.getElementById("btnFindNext");
- btnFindNext.src = "images/btnNextIn.gif";
- gTimeoutInterval = setTimeout
- (searchTree, 100, true, txtToFind, searchURL);
- }
- else
- {
- // Find Prev page with matching <textbox...> text
- btnFindPrev = document.getElementById("btnFindPrev");
- btnFindPrev.src = "images/btnPrevIn.gif";
- gTimeoutInterval = setTimeout
- (searchTree, 100, false, txtToFind, searchURL);
- }
- }
- }
-
- // ============================================================
- // Called from "historyViewer.xul" <textbox ...> onkeyup event
- // ============================================================
- function searchTextboxEventHandler(event)
- {
- // Make <textbox...> background red if text is not found
- var chkSearchURL = document.getElementById("chkSearchURL");
- if (!chkSearchURL.disabled)
- setSearchTextBoxColor(chkSearchURL.checked);
- }
-
- // =============================================================
- // Called from "historyViewer.xul" <checkbox ...> onclick event
- // =============================================================
- function searchCheckboxEventHandler(event)
- {
- // Do nothing if <checkbox...> is disabled
- if (!event.target.disabled)
- {
- // Make <textbox...> background red if text is not found
- var checked = !event.target.checked;
- Application.storage.set("searchCheckboxVal", checked);
- setSearchTextBoxColor(checked);
- }
- }
-
- // ===============================================================
- // Called from TWO "historyViewer.xul <image...> onclick() events
- // ===============================================================
- function imageButtonClickEventHandler(event)
- {
- // Exit if a setInterval() or setTimeout() is running
- if (setIntervalOrTimeoutRunning() || gNodeList.length === 0)
- return;
-
- // Get "historyViewer.xul" controls and init vars
- var btnGridView = document.getElementById("btnGridView");
- var btnTreeView = document.getElementById("btnTreeView");
- var sldDraw = document.getElementById("sldDraw");
- var lblSliderHdr = document.getElementById("lblSliderHdr");
- var optGrpView = document.getElementById("optGrpView");
- var borderSize = 0;
-
- // --------------------------------------------
- if (event.target.id === "btnGridView"
- && btnGridView.src === "images/btnGVout.gif")
- // --------------------------------------------
- {
- // Change to GridView and save it to App Storage
- gCurrentView = GRID_VIEW;
- Application.storage.set("GVorTVbuttonVal", GRID_VIEW);
-
- // Change GUI controls for GridView
- btnGridView.src = "images/btnGVin.gif";
- btnTreeView.src = "images/btnTVout.gif";
-
- // Set <scale...> (slider) attributes
- sldDraw.value = Application.storage.get("gridViewSliderVal", 4);
- lblSliderHdr.value = "Image Size";
-
- // Draw all ".jpeg" images on the gCanvas
- var numAcross = (sldDraw.max - sldDraw.value) + 3;
- drawAllImagesOnCanvas(numAcross, true);
- }
-
- // --------------------------------------------
- if (event.target.id === "btnTreeView"
- && btnTreeView.src === "images/btnTVout.gif")
- // --------------------------------------------
- {
- // Change to TreeView and save it to App Storage
- gCurrentView = TREE_VIEW;
- Application.storage.set("GVorTVbuttonVal", TREE_VIEW);
-
- // Change GUI controls for TreeView
- btnTreeView.src = "images/btnTVin.gif";
- btnGridView.src = "images/btnGVout.gif";
-
- // Set <scale...> (slider) attributes
- sldDraw.value = Application.storage.get("treeViewSliderVal", 1);
- lblSliderHdr.value = "Tree Spacing";
-
- // Reset tree-spacing using slider value
- borderSize = (sldDraw.value * BORDER_STEP) + NODE_BORDER;
- setBorderForAllNodes(borderSize);
-
- // Draw tree, scrolling as required
- if (optGrpView.selectedIndex === 0)
- // "Show open tabs"
- drawTree(false, gCurrentTabID, null);
- else
- // Other quick-views
- drawTree(true, null, null);
- }
- }
-
- // ====================================================================
- // Called from "historyViewer.xul <scale...> onmouseup() and onkeyup()
- // ====================================================================
- function sliderChangeEventHandler(event)
- {
- // Exit if a setInterval() or setTimeout() is running
- if (setIntervalOrTimeoutRunning() || gNodeList.length === 0)
- return;
-
- // Clear the gCanvas
- gCtx.fillStyle = CANVAS_BAK_COL; // Dark grey
- gCtx.fillRect(0, 0, gCanvas.width, gCanvas.height);
-
- // Draw all nodes on gCanvas depending on current view
- var sliderVal = event.target.value;
- if (gCurrentView === GRID_VIEW)
- {
- // Draw all images on the gCanvas
- Application.storage.set("gridViewSliderVal", sliderVal);
- var numAcross = (event.target.max - sliderVal) + 3;
- drawAllImagesOnCanvas(numAcross, true);
- }
- else
- {
- // Reset tree-spacing then redraw tree
- Application.storage.set("treeViewSliderVal", sliderVal);
- var borderSize = (sliderVal * BORDER_STEP) + NODE_BORDER;
- setBorderForAllNodes(borderSize);
- drawTree(false, null, null);
- }
- }
-
- // =========================================================
- // Called from "historyViewer.xul" <listbox ...> onclick()
- // Redraws FULL Tab sub-tree (collapsed sub-trees reappear)
- // =========================================================
- function listboxClickEventHandler(event)
- {
- // Exit if a setInterval() or setTimeout() is running
- if (setIntervalOrTimeoutRunning() || gNodeList.length === 0)
- return;
-
- // Set <radiogroup ...> option for "Show selected tab" quick-view
- var optGrpView = document.getElementById("optGrpView");
- optGrpView.selectedIndex = 2;
- Application.storage.set("quickViewOptGrpVal", 2);
-
- // Show the "Show selected tab" quick-view
- showQuickView(2);
- }
-
- // =================================================================
- // Shows selected quick-view - Called from FOUR "historyViewer.xul"
- // <radio...> onclick() events and from <radiogroup...> onkeyup()
- // =================================================================
- function quickViewOptEventHandler(optNum)
- {
- // Exit if a setInterval() or setTimeout() is running
- if (setIntervalOrTimeoutRunning() || gNodeList.length === 0)
- return;
-
- // Get optNum from <radiogroup...> if its onkeyup() fired
- var optGrpView = document.getElementById("optGrpView");
- if (optNum === -1)
- optNum = optGrpView.selectedIndex;
-
- // Show GV or TV quick-view for selected option
- optGrpView.selectedIndex = optNum; // Needed
- Application.storage.set("quickViewOptGrpVal", optNum);
- showQuickView(optNum);
- }
-
- // ==============================================================
- // Shows GV or TV quick-view for passed <radiogroup...> optNum
- // ==============================================================
- function showQuickView(optNum)
- {
- // Set TreeNode pointers for passed quick-view optNum
- setTreeNodePointersForSelectedQuickView(optNum);
-
- // Draw the required GV or TV quick-view on gCanvas
- if (gCurrentView === TREE_VIEW)
- {
- if (optNum === 0)
- // TV "Show open tabs"
- drawTree(false, gCurrentTabID, null);
- else
- // TV Other quick-views
- drawTree(true, null, null);
- }
- else
- {
- // Draw GV quick-view using req number of images per row
- var sldDraw = document.getElementById("sldDraw");
- var numAcross = (sldDraw.max - sldDraw.value) + 3;
- drawAllImagesOnCanvas(numAcross, true);
- }
- }
-
- // ==============================================================
- // Sets TreeNode pointers for passed optNum - BUT does not draw
- // ==============================================================
- function setTreeNodePointersForSelectedQuickView(optNum)
- {
- // Init vars
- var listSelTab; // <listbox...>
- var selItem; // <listbox...> item
-
- // -----------------------------------------------------
- // Set TreeNode pointers for passed quick-view optNum
- if (optNum === 0)
- {
- // "Show open tabs"
- setTreePointersFor_OpenTabsQuickView();
- }
- else if (optNum === 1)
- {
- // "Show open pages"
- setTreePointersFor_OpenPagesQuickView();
- }
- else if (optNum === 2)
- {
- // "Show selected tab" using <listbox...> item tabID
- listSelTab = document.getElementById("listSelTab");
- selItem = listSelTab.getSelectedItem(0);
- setTreePointersFor_SelectedTabQuickView(selItem.value);
- }
- else if (optNum === 3)
- {
- // "Show closed tabs"
- setTreePointersFor_ClosedTabsQuickView();
- }
- }
-
- // ===============================================================
- // Called when user clicks mouse on gCanvas in either GV or TV
- // ===============================================================
- function canvasMouseClickEventHandler(event)
- {
- // Exit if a setInterval() or setTimeout() is running
- if (setIntervalOrTimeoutRunning() || gGVdispInterval !== null
- || gNodeList.length === 0)
- return;
-
- // Get current <scrollbox...> scrollbars (x, y) positions
- var xs = {}; // object
- var ys = {}; // object
- gCanvasScroller.getPosition(xs, ys);
-
- // Get mouse click (x, y) adjusting for scrollbars (x, y)
- // where (0, 0) is top-left corner of window NOT gCanvas
- mouseX = event.clientX + xs.value;
- mouseY = event.clientY + ys.value - gCanvas.offsetTop;
-
- // ----------------------------------------------------
- // Do required action depending on the current view
- if (gCurrentView === GRID_VIEW)
- {
- // Get TreeNode for GV image user clicked on (if any)
- var tNode = gridViewTreeNodeFromMouseXY(mouseX, mouseY);
-
- // Open page in FF if user clicked on GV ".jpeg" image
- if (tNode !== null)
- openOrGotoSelectedHistoryPage(tNode);
- }
- else // TREE_VIEW
- {
- // Call "treeViewChanger.js" TV mouse-click handler
- respondToTreeViewMouseClickOnCanvas(mouseX, mouseY);
- }
- }
-
- // ****************************************************
- // ***** *****
- // ***** UTILITY FUNCTIONS *****
- // ***** USED BY "historyViewer.xul" JS FILES *****
- // ***** *****
- // ****************************************************
-
- // =========================================================
- // Called from "historyViewer.js" or "treeViewChanger.js"
- // when user clicks on a gCanvas TV TreeNode or GV ".jpeg"
- // =========================================================
- function openOrGotoSelectedHistoryPage(tNode)
- {
- // Show goto/open page modal Dialog window
- if (tNode !== null)
- {
- // Put App Storage data used by the window opened below
- Application.storage.set("openPageTreeNode", tNode);
-
- // Define a resizable dialog window with no max/min/close buttons and
- // no right-click context menu, which will open modally at center screen
- var chromeFeatures = "chrome,centerscreen,modal=yes,resizable=yes,close=no";
- var winPath = "chrome://historyTree/content/openPageDialog.xul";
- window.openDialog(winPath,"pageOpener",chromeFeatures);
- }
- }
-
- // =============================================================
- // ONLY called from modal window "openPageDialog.js" onUnload()
- // =============================================================
- function showHistoryPageInFirefox(optNum, selTabID)
- {
- // Check if user is opening a new page in FF
- if (optNum !== 0)
- {
- // Set global flags that will force full data update/refresh when
- // this window's onFocus() event fires (focus is changed below)
- gExitWinFocusEvent = false;
- gNodeListLoadLen = null;
- }
-
- // Set focus to current parent FF window (MUST be done first)
- gParentFFWin.focus();
-
- // Call "firefoxOverlay.js" method to open/goto history page
- var tNode = Application.storage.get("openPageTreeNode", null);
- if (tNode !== null)
- gParentFFWin.historyTree.openOrGotoHistoryPage(tNode, optNum, selTabID);
- }
-
- // ============================================================
- // Returns Next/Previous open FF window using cyclic retrieval
- // ============================================================
- function nextOrPrevFFwindow(nextWin)
- {
- var wm; // nsIWindowMediator
- var enum; // Simple nsI enumerator
- var win, reqWin; // Open FF windows
- var winList = new Array(); // List of open FF windows
- var currWinNum; // Integer
-
- // ---------------------------------------------------
- // Create array list of all open FF windows
- wm = Components.classes["@mozilla.org/appshell/window-mediator;1"]
- .getService(Components.interfaces.nsIWindowMediator);
- enum = wm.getEnumerator("navigator:browser");
-
- while (enum.hasMoreElements())
- {
- win = enum.getNext();
- winList.push(win);
- if (win === gParentFFWin)
- currWinNum = winList.length - 1;
- }
-
- // ---------------------------------------------------
- // Get Next/Prev open FF window using cyclic retrieval
- if (nextWin)
- {
- if (currWinNum === winList.length - 1)
- reqWin = winList[0];
- else
- reqWin = winList[currWinNum + 1];
- }
- else
- {
- if (currWinNum === 0)
- reqWin = winList[winList.length - 1];
- else
- reqWin = winList[currWinNum - 1];
- }
-
- // Clear temp array then return Next/Prev FF win
- winList.splice(0);
- return reqWin;
- }
-
- // ===================================================================
- // Set "Window x of y" label text - Called via onLoad() and onFocus()
- // ===================================================================
- function setLabelText_WindowXofY()
- {
- var wm; // nsIWindowMediator
- var enum; // Simple nsI enumerator
- var win; // Open FF window
- var currWinNum, numWin; // Integers
-
- // ------------------------------------------------
- // Get list of all open FF windows
- wm = Components.classes["@mozilla.org/appshell/window-mediator;1"]
- .getService(Components.interfaces.nsIWindowMediator);
- enum = wm.getEnumerator("navigator:browser");
-
- // Get numbers used for label
- numWin = 0;
- while (enum.hasMoreElements())
- {
- numWin ++;
- win = enum.getNext();
- if (win === gParentFFWin)
- currWinNum = numWin;
- }
-
- // Set "Window x of y" label text
- var lblWinInfo = document.getElementById("lblWinInfo");
- lblWinInfo.value = "Window " + currWinNum.toString()
- + " of " + numWin.toString();
- }
-
- // =================================================================
- // Disables or enables GUI controls while setInterval() running etc
- // =================================================================
- function disableOrEnableGUIcontrols(disable)
- {
- // Don't re-enable if no FF history
- if (!disable && gNodeList.length === 0)
- return;
-
- // Get references to "historyViewer.xul" GUI controls
- var optGrpView = document.getElementById("optGrpView");
- var listSelTab = document.getElementById("listSelTab");
- var txtFind = document.getElementById("txtFind");
- var chkSearchURL = document.getElementById("chkSearchURL");
- var sldDraw = document.getElementById("sldDraw");
-
- // Remove items from <listbox...> if disabling
- if (disable)
- {
- while (listSelTab.itemCount > 0)
- listSelTab.removeItemAt(0);
- }
-
- // Set search <textbox...> backcolor
- if (disable)
- txtFind.style.backgroundColor = "#cccccc"; // Grey
- else
- txtFind.style.backgroundColor = "#ffffff"; // White
-
- // Disable or enable other GUI controls
- optGrpView.disabled = disable;
- listSelTab.disabled = disable;
- chkSearchURL.disabled = disable;
- sldDraw.disabled = disable;
- }
-
- // ==============================================================
- // Loads node ".jpeg" from its dataURL, then draws it on gCanvas
- // This is only done ONCE for each node (to speed up redraws)
- // ==============================================================
- function drawAndUpdateNodeImage(node, x, y, w, h)
- {
- // Try to draw the node's ".jpeg" image on the gCanvas
- try
- {
- // Create node ".jpeg", then draw it on gCanvas *** NOTE
- // Many tests showed this to be the most reliable approach
- node = nodeWithImage(node);
- gCtx.drawImage(node.imgToDraw, x, y, w, h);
- }
- catch (e)
- {
- // Nothing will be drawn on gCanvas
- node.imgData = null;
- }
- }
-
- // =====================================================
- // Returns passed hNode with its ".jpeg" image loaded
- // =====================================================
- function nodeWithImage(hNode)
- {
- var img = new Image();
-
- // Wait until the image loads
- img.onload = function()
- {
- // Return node with image props set
- hNode.imgToDraw = img;
- hNode.imgCreated = true;
- return hNode;
- };
-
- // This MUST be done here or sometimes onload() is NOT called
- img.src = hNode.imgData;
- }
-
- // ==============================================================
- // Returns true if a blank rectangle is drawn instead of ".jpeg"
- // ==============================================================
- function blankRectangleDrawn(hNode, x, y, w, h, roundRect, bordCol)
- {
- // Init integers
- var suffixPos;
- var fontSize;
- var reqWid, txtWid;
- var textX, textY, yAddOn;
- var rectMsg; // String
-
- // -------------------------------------------
- // Check if a blank rectangle should be drawn
- suffixPos = hNode.uri.length - 4;
-
- if (hNode.imgData === null
- || hNode.uri.lastIndexOf(".pdf") === suffixPos)
- {
- rectMsg = "Image not available";
- }
- else
- {
- return false;
- }
-
- // -------------------------------------------
- // Draw a white rectangle with border
- if (roundRect)
- {
- // Rounded corner rect with highlighted border
- gCtx.lineWidth = 3;
- drawRoundedRectWithBorder
- (x - 2, y - 2, w + 4, h + 4, 10, "white", bordCol);
- }
- else
- {
- // Square rectangle with black border
- drawBorderedRect
- (x - 1, y - 1, w + 2, h + 2, "white", bordCol, 2);
- }
-
- // ---------------------------------------------
- // Init while() loop font/text sizing vars
- reqWid = Math.round(w * 0.6);
- fontSize = 7;
- gCtx.mozTextStyle = "bold " + fontSize.toString() + "pt verdana";
- txtWid = gCtx.mozMeasureText(rectMsg);
-
- // Keep increasing font size until rectMsg reaches reqWid
- while (txtWid < reqWid && fontSize < 14)
- {
- fontSize ++;
- gCtx.mozTextStyle = "bold " + fontSize.toString() + "pt verdana";
- txtWid = gCtx.mozMeasureText(rectMsg);
- }
-
- // Draw sized rectMsg text inside the rectangle
- textX = Math.round(x + (w - txtWid) / 2);
- textY = Math.round(y + (h / 2));
- yAddOn = Math.ceil((14 - fontSize) / 2);
- gCtx.fillStyle = "rgb(190,190,190)"; // Light grey
- fillText(rectMsg, textX, textY + yAddOn);
-
- // -------------------------------------------
- // White rectangle WAS drawn
- return true;
- }
-
- // ============================================================
- // Returns number of open Tab header TreeNode's in gTabRoots[]
- // ------------------------------------------------------------
- // *** NOTE - Blank FF Tabs are not shown AT ALL in GV or TV
- // ============================================================
- function numExtWinOpenTabs()
- {
- // Get count of open Tab TreeNode's in gTabRoots[]
- var tabRoot;
- var numOpen = 0;
- for (var ndx = 0; ndx < gTabRoots.length; ndx++)
- {
- tabRoot = gTabRoots[ndx];
- if (tabRoot.inOpenTab)
- numOpen ++;
- }
- // Return the count
- return numOpen;
- }
-
- // ================================================================
- // Use Mozilla method to draw text on the gCanvas
- // *** NOTE - This allows easy find/replace changeover for FF 3.5
- // mozTextStyle can also be globally replced with font()
- // ================================================================
- function fillText(text, x, y)
- {
- gCtx.translate(x, y);
- gCtx.mozDrawText(text);
- gCtx.translate((-1 * x), (-1 * y));
- //gCtx.fillRect(1,1,1,1);
- }
-
- // ======================================================
- // Clears gCanvas, then shows passed msg in passed font
- // ======================================================
- function showBigMessageOnEmptyCanvas(msg, font)
- {
- // Init vars
- var textX; // Integer
- var xs = {}; // object
- var ys = {}; // object
-
- // --------------------------------------------
- // Clear the gCanvas
- gCtx.fillStyle = CANVAS_BAK_COL; // Dark grey
- gCtx.fillRect(0, 0, gCanvas.width, gCanvas.height);
-
- // Calculate x co-ordinate for drawing passed msg
- gCtx.mozTextStyle = font;
- textX = Math.round((this.innerWidth - gCtx.mozMeasureText(msg)) / 2);
- if (textX < 0)
- textX = 0;
-
- // Show "Loading..." message centre screen
- gCanvasScroller.getPosition(xs, ys);
- gCtx.fillStyle = "white";
- fillText(msg, xs.value + textX, ys.value + 85);
- }
-
- // =======================================================
- // Returns a "trimmed" version of the passed string
- // =======================================================
- function trim(s)
- {
- s = s.replace( /^\s*/, ""); // Trims leading spaces
- s = s.replace( /\s*$/, ""); // Trims trailing spaces
- return s;
- }
-
- // =======================================================
- // Returns a "truncated" version of passed string
- // =======================================================
- function truncatedText(text, reqWidth)
- {
- text = trim(text); // Trim passed text
- var truncText = text;
- var len = text.length;
-
- // Keep chopping chars off end of text until its short enough
- while(gCtx.mozMeasureText(truncText) > reqWidth && truncText.length > 0)
- {
- len--;
- truncText = text.substring(0, len);
- }
-
- // Return truncated string or original if not truncated
- truncText = trim(truncText);
- if (truncText.length < text.length)
- return truncText.substring(0, len - 1) + "...";
- else
- return text;
- }
-
- // =========================================================
- // ****** TEST FUNCTION ******
- // Returns a string describing properties of passed obj
- // =========================================================
- function showPropertiesOf(obj)
- {
- var rowTot = 0;
- var propList = "";
-
- for (var prop in obj)
- {
- propList += prop + " = " + obj[prop] + "....";
- rowTot ++;
- if (rowTot > 4)
- {
- rowTot = 0;
- propList += "\n";
- }
- }
- return propList;
- }
-